<?php
/**
 * Description: 用户登录
 * User: devforma
 * Date: 15/1/4
 * Time: 21:00
 */
require LIB_DIR.'/phpass.class.php';

class UserLogin implements iController {

    private $validateUser, $guestId, $weixinDetect = false, $weixinOpenid = '';
    private $registerSource, $registerChannel, $campusChannel, $activity;

    /**
     * api请求处理主函数
     * @param array $queryArgs 就是$_REQUEST变量
     * @return array api返回结果，必须含response_code
     */
    public function output($queryArgs) {
        $this->validateUser = validateUser($queryArgs);
        if ($queryArgs['login_type'] === '' || !is_numeric($queryArgs['login_type'])
            || empty($queryArgs['login_id'])) {
            return genOutput(1000); //参数错误
        }

        //获取注册渠道来源
        $registerInfo = getRegisterInfo($queryArgs);
        $this->registerSource  = $registerInfo['register_source'];
        $this->registerChannel = $registerInfo['register_channel'];
        $this->campusChannel   = $registerInfo['campus_channel'];
        $this->activity        = $registerInfo['register_activity'];

        //游客身份，需记录游客id
        if ($this->validateUser == 2)
            $this->guestId = $queryArgs['guest_id'];

        switch ($queryArgs['login_type']) {
            case 0: //手机号或邮箱登录
                $output = $this->loginByPhoneOrEmail($queryArgs['login_id'], $queryArgs['password']);
                break;

            case 1: //新浪微博
                $output = $this->loginBy('weibo', $queryArgs['login_id'], $queryArgs['nickname'], $queryArgs['avatar']);
                break;

            case 2: //微信

                if (!empty($queryArgs['app_type']) && $queryArgs['app_type'] === 'dailyplan'
                    && !empty($queryArgs['app_version']) && version_cmp($queryArgs['app_version'], '1.1') >= 0
                    && !empty($queryArgs['weixin_openid'])) {
                    $this->weixinDetect = true;
                    $this->weixinOpenid = $queryArgs['weixin_openid'];
                }

                $output = $this->loginBy('weixin', $queryArgs['login_id'], $queryArgs['nickname'], $queryArgs['avatar']);
                break;

            case 3: //验证码
                if (!empty($queryArgs['user_id']) && !validateUser($queryArgs)) { //如果有user信息则验证
                    $output = genOutput(1000);

                } else {
                    $output = $this->loginByToken($queryArgs['login_id'], $queryArgs['mobile_token'],
                        $queryArgs['user_id']);
                }

                break;

            default:
                $output = genOutput(1000);
                break;
        }

        return $output;
    }

    /**
     * 手机验证码登录
     * @param string $phone 手机号
     * @param string $token 验证码
     * @param int $userId 用户id
     * @return array
     */
    private function loginByToken($phone, $token, $userId) {
        global $uddb;

        if (empty($phone) || empty($token))
            return genOutput(1000);

        $cacheKey = 'phone:'.$phone;
        $value = cacheGet($cacheKey);

        if (!isset($value['token_login']) || $value['code'] != $token) {
            return genOutput(1000);
        }

        $sql = "SELECT * FROM `{$uddb->userAuthInfo}` WHERE `phone`=:phone";
        $exist = $uddb->getRow($sql, array(':phone' => $phone));

        if (!empty($exist)) { //手机号已存在
            $socialInfo = $uddb->getRow("SELECT * FROM `{$uddb->userSocialInfo}` WHERE `user_id`=".$exist->ID);

            //清除该手机号的cache
//            cacheDelee($cacheKey);

            //兼容每日一题的头像保存url
            if (!empty($socialInfo->avatar) && strpos($socialInfo->avatar, 'http://') === false) {
                $socialInfo->avatar = 'http://edu.appublisher.com/user-images/avatar/'.$socialInfo->avatar;
            }

            //更改校验状态，用于之后更改密码
            $value['validated'] = true;
            cacheSet($cacheKey, $value);

            return genOutput(1, array(
                'is_new' => false,
                'user' => array(
                    'user_id' => intval($exist->ID),
                    'user_token' => $exist->user_token,
                    'mobile_num' => $exist->phone,
                    'avatar' => empty($socialInfo->avatar) ? '' : $socialInfo->avatar,
                    'mail' => '',
                    'area' => '',
                    'birthday' => '',
                    'career' => '',
                    'nickname' => $socialInfo->nickname,
                    'address' => empty($socialInfo->address) ? '' : $socialInfo->address,
                    'sno' => intval($socialInfo->user_sno),
                    'weibo' => empty($exist->weibo) ? '' : $exist->weibo,
                    'weixin' => empty($exist->weixin) ? '' : $exist->weixin,
                    'enable_interview' => $this->checkInterviewStatus($exist->ID),
                    'related_phone' => empty($exist->related_phone) ? '' : $exist->related_phone,
                    'qq' => (string)$socialInfo->qq
                ),
                'exam' => $this->getExamInfo($exist->ID)
            ));

        } else { //手机号未存在
            if (!empty($userId)) { //绑定手机号动作
                $uddb->update($uddb->userAuthInfo, array('phone' => $phone), array('ID' => $userId));
                $socialInfo = $uddb->getRow("SELECT * FROM `{$uddb->userSocialInfo}` WHERE `user_id`=".$userId);
                $authInfo = $uddb->getRow("SELECT * FROM `{$uddb->userAuthInfo}` WHERE `ID`=:uid",
                    array(':uid' => $userId));

                //清除该手机号的cache
                cacheDelete($cacheKey);

                //清除用户信息缓存
                cacheDelete('userInfo:'.$userId);

                //兼容每日一题的头像保存url
                if (!empty($socialInfo->avatar) && strpos($socialInfo->avatar, 'http://') === false) {
                    $socialInfo->avatar = 'http://edu.appublisher.com/user-images/avatar/'.$socialInfo->avatar;
                }

                return genOutput(1, array(
                    'is_new' => false,
                    'user' => array(
                        'user_id' => intval($authInfo->ID),
                        'user_token' => $authInfo->user_token,
                        'mobile_num' => $authInfo->phone,
                        'avatar' => empty($socialInfo->avatar) ? '' : $socialInfo->avatar,
                        'nickname' => $socialInfo->nickname,
                        'mail' => '',
                        'career' => '',
                        'area' => '',
                        'birthday' => '',
                        'address' => empty($socialInfo->address) ? '' : $socialInfo->address,
                        'sno' => intval($socialInfo->user_sno),
                        'weibo' => empty($authInfo->weibo) ? '' : $authInfo->weibo,
                        'weixin' => empty($authInfo->weixin) ? '' : $authInfo->weixin,
                        'enable_interview' => $this->checkInterviewStatus($authInfo->ID),
                        'related_phone' => empty($authInfo->related_phone) ? '' : $authInfo->related_phone,
                        'qq' => (string)$socialInfo->qq
                    ),
                    'exam' => $this->getExamInfo($authInfo->ID)
                ));

            } else { //创建新用户
                $uddb->insert($uddb->userAuthInfo, [
                    'user_pass'         => '',
                    'phone'             => $phone,
                    'register_source'   => $this->registerSource,
                    'register_channel'  => $this->registerChannel,
                    'register_activity' => $this->activity,
                    'campus_channel'    => $this->campusChannel,
                    'user_registered'   => date('Y-m-d H:i:s')
                ]);

                $userId = $uddb->lastInsertId();

                //生成登录token，并cache，便于其他api请求校验用户的有效性
                $userToken = md5($userId . ':' . ENCRYPTION_KEY);
                $uddb->update($uddb->userAuthInfo, array('user_token' => $userToken), array('ID' => $userId));

                $nickname = '*******' . substr($phone, 7);
                $sno = self::genSno($userId);
                $uddb->insert($uddb->userSocialInfo, array('user_id' => $userId, 'nickname' => $nickname, 'user_sno' => $sno));

                //清除该手机号的cache
                cacheDelete($cacheKey);

                return genOutput(1, array(
                    'is_new' => true,
                    'user' => array(
                        'user_id' => intval($userId),
                        'nickname' => $nickname,
                        'user_token' => $userToken,
                        'mobile_num' => $phone,
                        'address' => '',
                        'mail' => '',
                        'avatar' => '',
                        'area' => '',
                        'birthday' => '',
                        'sno' => intval($sno),
                        'career' => '',
                        'weibo' => '',
                        'weixin' => '',
                        'enable_interview' => false,
                        'related_phone' => '',
                        'qq' => ''
                    ),
                    'exam' => new stdClass()
                ));
            }
        }

    }


    /**
     * 手机号登录
     * @param string $username 手机号或邮箱
     * @param string $passwd 密码
     * @return array 返回结果
     */
    private function loginByPhoneOrEmail($username, $passwd) {
        global $uddb;
        
        $passwd = passDecrypt($passwd, ENCRYPTION_KEY); //还原密码
        $phpass = new PasswordHash(8, true);
        
        if (strpos($username, '@') !== false) { //邮箱登录
            $query = "SELECT * FROM `{$uddb->userAuthInfo}` WHERE `user_email`=:username";
            $user = $uddb->getRow($query, array(':username' => $username));
        } elseif(validatePhone($username)) {
            //手机号登录
            $query = "SELECT * FROM `{$uddb->userAuthInfo}` WHERE `phone`=:phone";
            $user = $uddb->getRow($query, array(':phone' => $username));
        }
        
        //无此用户
        if (empty($user)) return genOutput(1107);
        
        $mobileNum = '';
        if (validatePhone($user->phone)) $mobileNum = $user->phone;

        //验证密码
        if ($phpass->CheckPassword($passwd, $user->user_pass)) {
            //用户尚未有token（可能来自email登录）
            if (empty($user->user_token)) {
                $user->user_token = md5($user->ID.':'.ENCRYPTION_KEY);
                $uddb->update($uddb->userAuthInfo,
                                  array('user_token' => $user->user_token),
                                  array('ID' => $user->ID)
                                  );
            }

            //更新cache，便于接口的用户有效性验证
            cacheSet('user:'.$user->ID, array('token' => $user->user_token, 'login_timestamp' => time()));
            
            //获取userinfo信息
            $sql = "SELECT * FROM `{$uddb->userSocialInfo}` WHERE `user_id`={$user->ID}";
            $userInfo = $uddb->getRow($sql);
            
            //兼容每日一题的头像保存url
            if (!empty($userInfo->avatar) && strpos($userInfo->avatar, 'http://') === false) {
                $userInfo->avatar = 'http://edu.appublisher.com/user-images/avatar/'.$userInfo->avatar;
            }

            return genOutput(1, array(
                'is_new' => false,
                'user' => array(
                    'user_id' => intval($user->ID),
                    'nickname' => $userInfo->nickname,
                    'user_token' => $user->user_token,
                    'mobile_num' => $mobileNum,
                    'avatar' => empty($userInfo->avatar) ? '' : $userInfo->avatar,
                    'mail' => empty($userInfo->email) ? '' : $userInfo->email,
                    'address' => empty($userInfo->address) ? '' : $userInfo->address,
                    'sno' => intval($userInfo->user_sno),
                    'weibo' => empty($user->weibo) ? '' : $user->weibo,
                    'weixin' => empty($user->weixin) ? '' : $user->weixin,
                    'enable_interview' => $this->checkInterviewStatus($user->ID),
                    'qq' => (string)$userInfo->qq
                ),
                'exam' => $this->getExamInfo($user->ID)
            ));
        }
            
        return genOutput(1106);
    }

    /**
     * 第三方平台登录
     *
     * @param string $socialName 第三方平台名称
     * @param string $socialId 第三方ID
     * @param string $nickname 昵称
     * @param string $avatar 头像url
     * @return array 返回结果
     */
    private function loginBy($socialName, $socialId, $nickname, $avatar) {
        global $uddb;
        
        $nickname = urldecode($nickname);
        $avatar = urldecode($avatar);
        
        if ($socialName == 'weixin' && $this->weixinDetect) {
            $userId = getUserIdWithWeixin($this->weixinOpenid, $socialId);

            $sql = "SELECT * FROM `{$uddb->userAuthInfo}` AS t1
                LEFT JOIN `{$uddb->userSocialInfo}` AS t2 ON(t1.ID=t2.user_id)
                WHERE t1.ID=:uid";

            $userInfo = $uddb->getRow($sql, array(":uid" => $userId));

        } else {
            $sql = "SELECT * FROM `{$uddb->userAuthInfo}` AS t1
                LEFT JOIN `{$uddb->userSocialInfo}` AS t2 ON(t1.ID=t2.user_id)
                WHERE `$socialName`=:$socialName";
            $userInfo = $uddb->getRow($sql, array(":$socialName" => $socialId));
        }

        //首次使用
        if (empty($userInfo)) {
            //表插入数据
            $uddb->insert($uddb->userAuthInfo, [
                $socialName        => $socialId,
                'register_source'  => $this->registerSource,
                'register_channel' => $this->registerChannel,
                'user_registered'  => date('Y-m-d H:i:s'),
                'register_activity'=> $this->activity,
                'campus_channel'   => $this->campusChannel
            ]);
            $userId = $uddb->lastInsertId();
            
            if (!is_numeric($userId)) return genOutput(1106);
            
            $userToken = md5($userId.':'.ENCRYPTION_KEY);
            $uddb->update($uddb->userAuthInfo,
                          array('user_token' => $userToken),
                          array('ID' => $userId)
                          );

            $sno = self::genSno($userId);
            $uddb->insert($uddb->userSocialInfo, array(
                'user_id' => $userId,
                'nickname' => $nickname,
                'avatar' => $avatar,
                'user_sno' => $sno
            ));
            
            //更新cache，便于接口的用户有效性验证
            cacheSet('user:'.$userId, array('token'=>$userToken, 'login_timestamp'=>time()));
            
            //游客身份进行第三方的首次登录，需关联游客历史数据
            if ($this->validateUser == 2)
                $this->updateGuestData($this->guestId, $userId);
                
            return genOutput(1, array(
                'is_new' => true,
                'user' => array(
                    'user_id' => intval($userId),
                    'nickname' => $nickname,
                    'user_token' => $userToken,
                    'mobile_num' => '',
                    'avatar' => $avatar,
                    'address' => '',
                    'mail' => '',
                    'sno' => intval($sno),
                    'weibo' => $socialName=='weibo' ? $socialId : '',
                    'weixin' => $socialName=='weixin' ? $socialId : '',
                    'enable_interview' => $this->checkInterviewStatus($userId),
                    'qq' => ''
                ),
                'exam' => new stdClass() //首次登陆第三方账号，exam信息使用app端，这里返回为空
            ));
        }
        
        // 非首次使用，但token为空
        if (empty($userInfo->user_token)) {
            $userInfo->user_token = md5($userInfo->user_id.':'.ENCRYPTION_KEY);
            $uddb->update($uddb->userAuthInfo,
                              array('user_token' => $userInfo->user_token),
                              array('ID' => $userInfo->user_id));
        }

        //更新cache，便于接口的用户有效性验证
        cacheSet('user:'.$userInfo->user_id, array('token' => $userInfo->user_token, 'login_timestamp' => time()));

        //兼容每日一题的头像保存url
        if (!empty($userInfo->avatar) && strpos($userInfo->avatar, 'http://') === false) {
            $userInfo->avatar = 'http://edu.appublisher.com/user-images/avatar/'.$userInfo->avatar;
        }
        
        return genOutput(1, array(
            'is_new' => false,
            'user' => array(
                'user_id' => intval($userInfo->user_id),
                'nickname' => $userInfo->nickname,
                'user_token' => $userInfo->user_token,
                'mobile_num' => validatePhone($userInfo->phone) ? $userInfo->phone : '',
                'avatar' => $userInfo->avatar,
                'mail' => $userInfo->email,
                'address' => empty($userInfo->address) ? '' : $userInfo->address,
                'sno' => intval($userInfo->user_sno),
                'weibo' => $userInfo->weibo==null ? '' : $userInfo->weibo,
                'weixin' => $userInfo->weixin==null ? '' : $userInfo->weixin,
                'enable_interview' => $this->checkInterviewStatus($userInfo->user_id),
                'qq' => (string)$userInfo->qq
            ),
            'exam' => $this->getExamInfo($userInfo->user_id)
        ));
    }

    /**
     * 游客数据关联
     * @param int $guestId 游客id
     * @param int $userId 用户id
     */
    private function updateGuestData($guestId, $userId) {
        global $uddb;
        
        $uddb->update($uddb->collection, array('user_id'=>$userId, 'guest_id'=>0),
            array('guest_id'=>$guestId));

        $uddb->update($uddb->historyMissionAction, array('user_id'=>$userId, 'guest_id'=>0),
            array('guest_id'=>$guestId));

        $uddb->update($uddb->userTests, array('user_id'=>$userId, 'guest_id'=>0),
            array('guest_id'=>$guestId));

        $uddb->update($uddb->recentAvMission, array('user_id'=>$userId, 'guest_id'=>0),
            array('guest_id'=>$guestId));

        $uddb->update($uddb->recentMissionInfo, array('user_id'=>$userId, 'guest_id'=>0),
            array('guest_id'=>$guestId));

        $uddb->update($uddb->userDPData, array('user_id'=>$userId, 'guest_id'=>0),
            array('guest_id'=>$guestId));
    }

    /**
     * 获取用户的考试项目信息
     * 
     * @param int $userId 用户id
     * @return array|stdClass 考试信息
     */
    private function getExamInfo($userId) {
        global $uddb, $cmsdb;

        switch ($_GET['app_type']) {
            case 'dailyplan':
                //检验是否开启上岸计划
                $sql = "SELECT `testarea_id` FROM `{$uddb->userDPData}` WHERE `user_id`={$userId}";
                $testId = $uddb->getVar($sql);
                break;

            case 'quizbank':
                //检验是否开启了天天模考
                $sql = "SELECT `exam_detail_id` FROM `qb_user_data` WHERE `user_id`={$userId}";
                $testId = $cmsdb->getVar($sql);
                break;

            case 'dailylearn':
                $sql = "SELECT `test_id` FROM `user_social_info` WHERE `user_id`={$userId}";
                $testId = $uddb->getVar($sql);
                break;

            default:
                break;
        }

        //考试项目信息
        if (!empty($testId)) {
            return getExamDetail($testId);
        }

        return new stdClass();
    }


    /**
     * 生成用户的学号
     * @param int $userId 用户id
     * @return string 学号
     */
    private static function genSno($userId) {
        return substr(strval(time()), -7).substr('00000'.$userId, -3);
    }


    /**
     * 检测面试开启情况
     *
     * @param int $userId 用户id
     * @return bool
     */
    private function checkInterviewStatus($userId) {
        global $cmsdb;

        $exists = $cmsdb->getVar('SELECT `id` FROM `relation_user_product` WHERE `user_id`=:uid AND `product_id`=1128 AND `product_type`="interview"',
            array(':uid' => $userId));

        return !empty($exists);
    }
}
